最近投了个稿介绍 smaji cjkv. 收到了几个审稿意见,建议在稿件中补充些引用及前置信息。这也是符合预期的。毕竟,大多学科,工程的发展,都是有延续性的。自然得建立在前人的基础上做发展。
我虽想补充这方面的引用,但一开始还是觉得有点困难。因为近二十年在异体字,罕用字录入,编码,字体这方面,我们虽时有探索,但都没有形成很大影响力。大多为自成一体,无法融入通用体系的私用系统。其中有相对开放的,则成了开放用户介面的私用系统,开放又通行的,则基础架构失能,都不能作为后续发展的基础。不值得放在引用和前置知识里。
Unicode 于 1999 年在 Unicode 3.0 引入了自己的 Ideographic Description Characters. 它天然地融入通用体系,覆盖面又广,使用方便。比如,“时间”,二字,分别可表示为“⿰日寸”,“⿵门日” 。即使复杂如“𰻝𰻝面”中的“𰻝”字,也可以表示为“⿺辶⿳穴⿲月⿱⿲幺言幺⿲长马长刂心”。乍一看,功能是很完备的。
点击查看𰻝字
但问题是,遇到“丝”,则无法分解。因为 Unicode 未收录“幺”去除最后一点的字。再比如“乔”,上“夭”下“?”,也是未收录字。再比如以下字的分解:“与”,“乌”,“亇”,“争”,“亥”,“以”……
因为太多的“组件”其实并无相应的字与其对应,而这套系统又要求其定义域,和值域皆为 Unicode 收录库。所以这套系统设计,一开始就缺损而无法完备:即使对常用字,都无法做到描述。
其余的私用系统,有意识到这个问题后放宽了定义域的限制,引入了私有组件。但汉字的组合方式多样,表意文字描述序列只能描述一些理想组合方式。稍稍不那么理想,譬如“⿻”,意思是两个组件相重叠,但具体是怎么重叠,重叠方向如何,重叠程度如何?全无描述。于是,无法从表意文字描述序列中还原字形。结果是又多了几套缺损而不完备的系统。
不过,审稿意见也促使我再一遍思考,过去的努力和遗产,是否还有价值,或者,经过改造提炼后,还能发挥作用么?
将过去的探索的的遗憾综合总结下,可列出如下几条:
-
组合组件定义域受限
-
表意文字描述序列缺乏精确性
-
不通用或应用场景受限
而解决方法的设计也相应的:
-
组合组件定义域受限
首先当然是解除这一限制,且解除限制的方式又不能带来新的问题。所以需满足如下条件:
-
不限制定义域仅为 Unicode 收录字。因其不完备。
-
定义的基础组合必须能够组合任意字符。否则即成另一不完备系统。
-
不得任意新增,删减,修改基础组合组件。以免造成组合方式失效以及不稳定。
结合这三点要求,不难想到,基础笔画即是符合以上所有要求的理想选择。但不能只是粗糙地选取五类笔画,而是要列举至少 63 种基础笔画,以及额外的镜像,旋转操作符才够用。因为,汉字是含有镜像字和倒置字的。
-
-
表意文字描述序列缺乏精确性
表意文字描述序列能描述的结构有其范式,即所描述的组件是垂直居中分隔的(⿱,⿳)或是水平居中分隔的(⿰,⿲)或是居中嵌合的(⿴)或是边包围的(⿵,⿶,⿷,)或是角包围的(⿸,⿹,⿺,)。这些描述符所操作的描述对象皆有外形,对于居中分隔的文字,只需计算长或宽取平均值,各个组件就能依据均值调整长宽比,取得新形状。包围结构的话,内部组件被嵌合,只需按外部组件依比例缩小,即取得新外形。
描述符 ⿻ 代表描述两个操作子(被操作对象)是相互重叠的,即边界失效。于是在组件排布中就组件外形就不能作为计算依据。而除此之外,描述符(IDS)和操作对象(笔画,字根)没有内禀性的其他任何计算依据,于是导致了这一描述系统的失能。
所以,我们就得引入额外的信息来补足缺损。分隔或包围描述符所描述的组件有其外形,描述的组合也有其组合外形,组合外形即为框外形。其中共有几种数据:外框的大小和位置,组件在外框内嵌合后的大小和位置。于是最后可以得出组件以框为座标系原点的位置和大小信息。
描述符 ⿻ 失能了组件形状后,相应的外框计算就无法进行了。于是组件的位置信息和大小信息都无法进行计算。于是,我们需补足的,即这两个信息。有了这两个信息,框大小也可通过用矩形最小化包围两个组件的方式来得出。
要描述平面位置和大小信息,我们需引入平面座标系来进行了。
平面座标的描述是个值得展开的话题,我们将其放在后面讨论。现在,我们暂且看看缺陷3.
-
不通用或应用场景受限
Unicode 有作为标准信息交换字符集的要求,所以组件必须从自身集中选取。而自身集收录的基础组件尚不能覆盖必需的基础组件。再加上 Unicode 自己的 Ideographic Description Characters(IDC) 描述能力不完备。于是造成了缺陷 1, 2.
而 Unicode 之外的高校,技术团体,商业机构也尝试过设计或实现出 Unicode 兼容又具有完备描述能力的系统。大部分接近完备,有一些则没有保持 Unicode 的兼容性,以致应用场景受限。
另外一个重要的原因是,对灵活性和实时性的要求很难满足。比如,学者需要引用古籍中的片段,但其中的几个文字有多个变体,并没有被标准收录。或是新发掘出了古籍,出现了之前没见过的字,需要将其引入标准,并更新所有人的计算机系统,才能正常编码,显示。
以上的要求都需要走一个漫长并且很可能不会成功的流程,会影响写文章的进度。
这个问题的解决方案在 Smaji CJKV 有给出,因此不再赘述了。
事实上, Smaji CJKV 在一开始并未设想设计一个字形描述系统。接受的仅是位图或者矢量图的录入。当核心系统能够兼容运作后。描述系统的设计变得可能。而前面提到的审稿意见对于补充信息的要求,让我重新思考了过去的经验,然后才开始着手字形描述语言的设计。
然后,我们就来解决之前跳过的问题:
-
表意文字描述序列缺乏精确性
此问题的解决思路和方法,需更多篇幅进行讲述,所以另起下述小节进行。
字形轮廓描述语言 (Glyph Outline Description Language)
因为此语言的标准形式是 xml, 所以最适合用 XML Schema Definition 来描述它。以下是这门语言的精确语法描述文档 god.xsd
创建 XML 文档
XML 文档由可选的 XML声明,可选的文档类型声明,文档(根)元素组成。
XML 版本的声明可以保证未来的 XML 的变更不会影响此文档的语法语义,编码声明可以告诉 XML 处理器此文档采用的编码. GOD 1.0 文档的采用的 XML版本为 1.0, 编码为 UTF-8
. 所以其 XML 编码头固定为:
<?xml version="1.0" encoding="UTF-8"?>
因为 xml 版本默认为 1.0, 且编码默认可接受 UTF-8
及 UTF-16
, 所以以上声明头并不是必需的。
1
2
3
4
5
6
7
8
9
10
<?xml version="1.0"?>
<god version="1.0"
xmlns="http://cjkv.smaji.org/ns/god"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://cjkv.smaji.org/ns/god http://cjkv.smaji.org/xml/1.0/xsd/god.xsd">
<glyph unicode="516b,0">
<stroke type="t" x="0" y="0" width="56" height="112"/>
<stroke type="p" x="76" y="0" width="56" height="112"/>
</glyph>
</god>
第一行是一个可选的 XML 声明。
第二行和第十行开始并结束一个 god
根元素。根元素主要用于表明此 god
文档的版本。第二行的 version 属性就表明了此 god
文档采用 1.0 版本的语法和语义。
第四行和第五行是可选的,用于引入此 god
文档的 XSD 描述以便文本编辑器可以通过它来验证正在编辑的 god
文档的正确性,并提供自动补全等建议。
接下来的子元素为 glyph
. 它含有一个必需属性 unicode
, 用于表明此 god
文档所描述的字形的 unicode
. 它的值为 16进制表示的 unicode
值,可在值后通过逗号分隔来附加变体选择子
的值。示例的 unicode
值为 516b, 即中文「八」的 unicode
编码。
「八」由两个笔画组成,第一笔为撇,第二笔为捺,于是在 glyph
元素的中,我们添加两个子元素,分别为笔画 t
(撇) 和笔画 p
(捺). 并给出了两个笔画的 x, y 轴位置信息,宽度,长度信息。关于笔画类型的 god
描述。请查询 god.xsd
描述文件。
下表是参考手册的摘录,可供参考。
点击查看参考手册摘录
h | Horizontal sh | Slanted Horizontal u | Upward horizontal du | Dot – Upward horizontal v | Vertical sv | Slanted Vertical rsv | Right Slanted Vertical t | Throw ft | Flat Throw wt | Wilted Throw d | Dot ed | Extended Dot ld | Left Dot wd | Wilted Dot p | Press up | Upward horizontal – Press hp | Horizontal – Press fp | Flat Press ufp | Upward horizontal – Flat Press c | Clockwise curve a | Anticlockwise curve o | Oval hj | Horizontal – J hook uj | Upward horizontal – J hook ht | Horizontal – Throw hsv | Horizontal – Slanted Vertical hv | Horizontal – Vertical hvj | Horizontal – Vertical – J hook htj | Horizontal – Throw – J hook utj | Upward horizontal – Throw – J hook hvh | Horizontal – Vertical – Horizontal hvu | Horizontal – Vertical – Upward horizontal ha | Horizontal – Anticlockwise curve haj | Horizontal – Anticlockwise curve – J hook hpj | Horizontal – Press – J hook htaj | Horizontal – Throw – Anticlockwise curve – J hook htc | Horizontal – Throw – Clockwise curve htht | Horizontal – Throw – Horizontal – Throw htcj | Horizontal – Throw – Clockwise curve – J hook hvhv | Horizontal – Vertical – Horizontal – Vertical hthtj | Horizontal – Throw – Horizontal – Throw – J hook vu | Vertical – Upward horizontal vh | Vertical – Horizontal va | Vertical – Anticlockwise curve vaj | Vertical – Anticlockwise curve – J hook vhv | Vertical – Horizontal – Vertical vht | Vertical – Horizontal – Throw vhtj | Vertical – Horizontal – Throw – J hook vj | Vertical – J hook vc | Vertical – Clockwise curve vcj | Vertical – Clockwise curve – J hook tu | Throw – Upward horizontal th | Throw – Horizontal td | Throw – Dot wtd | Wilted Throw – Dot tht | Throw – Horizontal – Throw thtj | Throw – Horizontal – Throw – J hook tj | Throw – J hook cj | Clockwise curve – J hook fpj | Flat Press – J hook pj | Press – J hook thtaj | Throw – Horizontal – Throw – Anticlockwise curve – J hook tod | Throw – Oval – Dot
点击查看对应图示
Stroke | Chinese name | Abbr form | Full name | Name in Unicode | Example |
---|---|---|---|---|---|
橫 |
H |
Horizontal |
H |
三 言 隹 花 |
|
斜橫 |
SH |
Slanted Horizontal |
(H) |
七 弋 宅 戈 |
|
挑 |
U |
Upward horizontal |
T |
刁 求 虫 地 |
|
點挑 |
DU |
Dot – Upward horizontal |
(T) |
冰 冷 汗 汁 |
|
豎 |
V |
Vertical |
S |
十 圭 川 仆 |
|
斜豎 |
SV |
Slanted Vertical |
(S) |
丑 五 亙 貫 |
|
右斜豎 |
RSV |
Right Slanted Vertical |
(S) |
𠙴 |
|
撇 |
T |
Throw |
P |
竹 大 乂 勿 |
|
扁撇 |
FT |
Flat Throw |
(P) |
千 乏 禾 斤 |
|
直撇 |
WT |
Wilted Throw |
SP |
九 厄 月 几 |
|
點 |
D |
Dot |
D |
主 卜 夕 凡 |
|
長點 |
ED |
Extended Dot |
(D) |
囪 囟 这 凶 |
|
左點 |
LD |
Left Dot |
(D) |
心 忙 恭 烹 |
|
直點 |
WD |
Wilted Dot |
(D) |
六 文 宇 空 |
|
捺 |
P |
Press |
N |
人 木 尺 冬 |
|
挑捺 |
UP |
Upward horizontal – Press |
TN |
文 廴 父 爻 |
|
橫捺 |
HP |
Horizontal – Press |
(TN) |
入 八 內 全 |
|
扁捺 |
FP |
Flat Press |
(N) |
走 足 廴 麵 |
|
挑扁捺 |
UFP |
Upward horizontal – Flat Press |
(TN) |
之 乏 巡 迴 |
|
彎 |
C |
Clockwise curve |
W |
||
曲 |
A |
Anticlockwise curve |
X |
||
圈 |
O |
Oval |
Q |
〇 㔔 㪳 㫈 |
|
橫鈎 |
HJ |
Horizontal – J hook |
HG |
冧 欠 冝 蛋 |
|
挑鈎 |
UJ |
Upward horizontal – J hook |
(HG) |
也 乜 池 馳 |
|
橫撇 |
HT |
Horizontal – Throw |
HP |
夕 水 登 令 |
|
橫斜 |
HSV |
Horizontal – Slanted Vertical |
(HP) |
今 彔 互 恆 |
|
橫豎 |
HV |
Horizontal – Vertical |
HZ |
口 己 臼 典 |
|
橫豎鈎 |
HVJ |
Horizontal – Vertical – J hook |
HZG |
而 永 印 令 |
|
橫撇鈎 |
HTJ |
Horizontal – Throw – J hook |
(HZG) |
勺 方 力 母 |
|
挑撇鈎 |
UTJ |
Upward horizontal – Throw – J hook |
(HZG) |
也 乜 池 馳 |
|
橫豎橫 |
HVH |
Horizontal – Vertical – Horizontal |
HZZ |
凹 兕 卍 雋 |
|
橫豎挑 |
HVU |
Horizontal – Vertical – Upward horizontal |
HZT |
殼 鸠 说 计 |
|
橫曲 |
HA |
Horizontal – Anticlockwise curve |
HZW |
朵 沿 殳 没 |
|
橫曲鈎 |
HAJ |
Horizontal – Anticlockwise curve – J hook |
HZWG |
九 几 凡 亢 |
|
橫捺鈎 |
HPJ |
Horizontal – Press – J hook |
(HZWG) |
風 迅 飛 凰 |
|
橫撇曲鈎 |
HTAJ |
Horizontal – Throw – Anticlockwise curve – J hook |
HXWG |
乙 氹 乞 乭 |
|
橫撇彎 |
HTC |
Horizontal – Throw – Clockwise curve |
--- |
過 过 這 这 |
|
橫撇橫撇 |
HTHT |
Horizontal – Throw – Horizontal – Throw |
HZZP |
延 建 巡 及 |
|
橫撇彎鈎 |
HTCJ |
Horizontal – Throw – Clockwise curve – J hook |
HPWG |
陳 陌 那 耶 |
|
橫豎橫豎 |
HVHV |
Horizontal – Vertical – Horizontal – Vertical |
HZZZ |
凸 𡸭 𠱂 𢫋 |
|
橫撇橫撇鈎 |
HTHTJ |
Horizontal – Throw – Horizontal – Throw – J hook |
HZZZG |
乃 孕 仍 盈 |
|
豎挑 |
VU |
Vertical – Upward horizontal |
ST |
卬 氏 衣 比 |
|
豎橫 |
VH |
Vertical – Horizontal |
SZ |
山 世 匡 直 |
|
豎曲 |
VA |
Vertical – Anticlockwise curve |
SW |
區 亡 四 匹 |
|
豎曲鈎 |
VAJ |
Vertical – Anticlockwise curve – J hook |
SWG |
孔 已 亂 也 |
|
豎橫豎 |
VHV |
Vertical – Horizontal – Vertical |
SZZ |
鼎 亞 吳 卐 |
|
豎橫撇 |
VHT |
Vertical – Horizontal – Throw |
(SZZ) |
奊 捑 𠱐 𧦮 |
|
豎橫撇鈎 |
VHTJ |
Vertical – Horizontal – Throw – J hook |
SZWG |
弓 弟 丐 弱 |
|
豎鈎 |
VJ |
Vertical – J hook |
SG |
小 水 到 寸 |
|
豎彎 |
VC |
Vertical – Clockwise curve |
SWZ |
肅 嘯 蕭 瀟 |
|
豎彎鈎 |
VCJ |
Vertical – Clockwise curve – J hook |
--- |
𨙨 𨛜 𨞠 𨞰 |
|
撇挑 |
TU |
Throw – Upward horizontal |
PZ |
去 公 玄 鄉 |
|
撇橫 |
TH |
Throw – Horizontal |
(SZ) |
互 母 牙 车 |
|
撇點 |
TD |
Throw – Dot |
PD |
巡 兪 巢 粼 |
|
直撇點 |
WTD |
Wilted Throw – Dot |
(PD) |
女 如 姦 㜢 |
|
撇橫撇 |
THT |
Throw – Horizontal – Throw |
(SZZ) |
夨 𠨮 专 砖 |
|
撇橫撇鈎 |
THTJ |
Throw – Horizontal – Throw – J hook |
(SZWG) |
巧 亟 污 號 |
|
撇鈎 |
TJ |
Throw – J hook |
PG |
乄 |
|
彎鈎 |
CJ |
Clockwise curve – J hook |
WG |
狗 豸 豕 象 |
|
扁捺鈎 |
FPJ |
Flat Press – J hook |
BXG |
心 必 沁 厯 |
|
捺鈎 |
PJ |
Press – J hook |
XG |
弋 戈 我 銭 |
|
撇橫撇曲鈎 |
THTAJ |
Throw – Horizontal – Throw – Anticlockwise curve – J hook |
--- |
𠃉 𦲳 𦴱 鳦 |
|
撇圈點 |
TOD |
Throw – Oval – Dot |
--- |
𡧑 𡆢 |
通过 CJKV Smaji 提供的字形轮廓生成程序处理后,产生了如下的字体轮廓文件。
除了直接用笔画组成字形外,在 god
中也能用已有的文字来组字。比如「丕」字就可由「不」字加「一」组成。
1
2
3
4
5
6
7
<?xml version="1.0"?>
<god version="1.0" xmlns="http://cjkv.smaji.org/ns/god">
<glyph unicode="4e15,0">
<ref unicode= "4e0d" x="0" y="0" width="128" height="120"/>
<stroke type="h" x="0" y="114" width="128" height="14"/>
</glyph>
</god>
当然,直接输入 unicode 虽然精确,但对于常用且无歧义的文字,直接打字也是个非常好的选择。上述 god
文件也可以改写成如下形式。将第 4 行改为
<character utf8= "不" x="0" y="0" width="128" height="120"/>
得到如下 god 文件
1
2
3
4
5
6
7
<?xml version="1.0"?>
<god version="1.0" xmlns="http://cjkv.smaji.org/ns/god">
<glyph unicode="4e15,0">
<character utf8= "不" x="0" y="0" width="128" height="120"/>
<stroke type="h" x="0" y="114" width="128" height="14"/>
</glyph>
</god>
均可产生如下字形轮廓:
我们再来看看另外一个字形轮廓:
它像不像是「了」被倒置过来了。确实是。汉字中存在着左右镜像字,上下镜像字,旋转字。图示便是一个旋转字。它在 god
里面又是怎么表示呢?
1
2
3
4
5
6
<?xml version="1.0"?>
<god version="1.0" xmlns="http://cjkv.smaji.org/ns/god">
<glyph unicode="2010f,0" transform="rotate180">
<character utf8="了" x="0" y="0" width="88" height="128" />
</glyph>
</god>
god
的一个设计理念是,对于隶定和隶变后的汉字,其构成是基础组件,笔画的组合,而不是对基础组件和笔画的操弄。因此,镜像或旋转操作仅可作用于字的整体。
因此,我们可以在 glyph
元素里增加 transform
属性,并给出
-
mirror_horizontal
-
mirror_vertical
-
rotate180
三者之一作为属性的值以指示转变。
因为 unicode
2010f 的字形正好是「了」字的旋转。所以在此 god
文件中,第 6 行指示了 transform
的属性为 rotate180
, 第 7 行则直接引入「了」字的字形作为基础。即得到了所需的字形。
Smaji CJVK 对于 GOD 的支持
Smaji Glyph Outline
一个 OCaml 库,用于读取,导出,转换字形轮廓数据和文件。
支持的字形轮廓格式为:
-
SVG, 可缩放矢量图形。使用极为广泛,支持异常丰富的矢量图形格式。
-
GLIF, 字形交换格式。用于 Unified Font Object
Smaji God
一个 OCaml 库,用于读取,处理,导出 GOD 文档。
Smaji DynGlyph
一个可执行程序,用户可通过它将 GOD 文档生成字体轮廓文件,轮廓文件可用于字体的生成。另外,也可以通过此程序生成笔画动画文件用于演示。
Smaji DynGlyph Collection
一个 git 仓库,存有 dyn-glyph 程序使用的示例基础笔画库,以及用户提交的 GOD 文档集合。
Online God Editor
在线编辑,提交 god 文件,并生成 svg 轮廓文件或动画文件。
Comments
comments powered by Disqus